#include <iostream>
#include <string>
#include <fstream>
#include <sys/stat.h>

#include <fstream>
#include <errno.h>
#include <cstring>
#define LOG(level_str, format, ...){\
    time_t t = time(nullptr);\
    struct tm* ptm = localtime(&t);\
    char time_str[32] = {0};\
    strftime(time_str, 31, "[%H:%M:%S]", ptm);\
    printf("[%s][%s][%s:%d] " format "\n", level_str, time_str, __FILE__, __LINE__, ##__VA_ARGS__);\
}
#define DLOG(format, ...) LOG("DEG", format, ##__VA_ARGS__)
#define ILOG(format, ...) LOG("INF", format, ##__VA_ARGS__)
#define ELOG(format, ...) LOG("ERR", format, ##__VA_ARGS__)
#define WLOG(format, ...) LOG("WAR", format, ##__VA_ARGS__)

class FileHelper
{
public:
    FileHelper(const std::string& filename)
        :_filename(filename)
    {}
    bool exists()
    {
        struct stat st;
        return stat(_filename.c_str(), &st) == 0; //只填一个文件名会去当前工作目录找
    }
    size_t size()
    {
        struct stat st;
        if(stat(_filename.c_str(), &st) < 0)
        {
            ELOG("%s,文件大小查看失败, errno %d: %s", _filename.c_str(), errno, strerror(errno));
            return 0;
        }
        return st.st_size; //这是成员，我靠
    }
    bool read(char* buffer)
    {
        return read(buffer, 0, this->size());
    }
    bool read(char* buffer, long long offset, size_t len)
    {
        std::ifstream ifs(_filename, std::ios::binary | std::ios::in); //以输入到程序  的方式打开文件
        if(ifs.is_open() == false)
        {
            ELOG("%s,文件读方式打开失败, errno %d: %s", _filename.c_str(), errno, strerror(errno));
            return false;
        }
        ifs.seekg(offset, std::ios::beg);
        ifs.read(buffer, len);
        if(ifs.good() == false)
        {
            ELOG("%s,文件读失败, errno %d: %s", _filename.c_str(), errno, strerror(errno));
            ifs.close();
            return false;
        }
        ifs.close();
        return true;
    }

    bool write(const char* buffer, long long offset, size_t len)
    {
        std::fstream fs(_filename, std::ios::binary | std::ios::in | std::ios::out); 
        if(fs.is_open() == false)
        {
            ELOG("%s,文件读写方式打开失败, errno %d: %s", _filename.c_str(), errno, strerror(errno));
            return false;
        }
        fs.seekg(offset, std::ios::beg);
        fs.write(buffer, len);
        if(fs.good() == false)
        {
            ELOG("%s,文件写入失败, errno %d: %s", _filename.c_str(), errno, strerror(errno));
            fs.close();
            return false;
        }
        fs.close();
        return true;
    }
    bool write(const std::string& buffer)   //大小不然拿不出来,目前感觉很鸡肋
    {
        return write(buffer.c_str(), 0, buffer.size());
    }
    bool rename(const std::string& newname)
    {
        return ::rename(_filename.c_str(), newname.c_str()) == 0;       //不写全局域可以找打吗？必须加，因为全局的rename被遮掩掉了
    }
    bool createFile()
    {
        std::ofstream ofs(_filename, std::ios::binary | std::ios::out); 
        if(ofs.is_open() == false)
        {
            ELOG("%s,文件方式打开失败, errno %d: %s", _filename.c_str(), errno, strerror(errno));
            return false;
        }
        return true;
    }
    bool removeFile()
    {
        return ::remove(_filename.c_str()) == 0;
    }
    static bool createDirectory(const std::string& path) //这个参数的要求是什么？？？
    {
        int pos = 0, idx = 0;
        while(idx < path.size())
        {
            pos = path.find("/", idx);
            if(::mkdir(path.substr(0, pos).c_str(), 0775) != 0)
            {
                ELOG("%s,目录创建失败, errno %d: %s", path.c_str(), errno, strerror(errno));
                return false;
            }
            idx = pos + 1;
        }
        return true;
    }
    static bool removeDirectory(const std::string& path)
    {
        std::string command = "rm -rf " + path;
        return ::system(command.c_str()) == 0; 
    }
    static std::string getParentDirectory(const std::string& filename)
    {
        int pos = filename.rfind("/");
        if(pos == std::string::npos)
            return "./";
        return filename.substr(0, pos);
    }
private:
    std::string _filename;
};


int main()
{

    return 0;
}